package com.jieshao.setting

import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.components.service
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.EditorSettings
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.highlighter.EditorHighlighter
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory
import com.intellij.openapi.editor.markup.EffectType
import com.intellij.openapi.editor.markup.HighlighterTargetArea
import com.intellij.openapi.editor.markup.MarkupModel
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.options.BoundConfigurable
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.wm.ex.WindowManagerEx
import com.intellij.openapi.wm.impl.IdeFrameImpl
import com.intellij.ui.CollectionComboBoxModel
import com.intellij.ui.JBColor
import com.intellij.ui.SimpleListCellRenderer
import com.intellij.ui.components.JBTextArea
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.icons.CachedImageIcon
import com.jetbrains.rd.util.string.printToString
import com.jieshao.rule.CustomRule
import com.jieshao.rule.Rule
import com.jieshao.script.innerEval
import com.jieshao.script.preScript
import com.jieshao.service.LineShareRuntime
import com.jieshao.utils.LineShareBundle
import com.jieshao.utils.LineShareBundle.message
import java.awt.Dimension
import java.awt.event.ItemEvent
import javax.swing.JList
import javax.swing.JOptionPane
import kotlin.reflect.KProperty0


class ProjectSettingsConfigurable(private val project: Project) : BoundConfigurable(message("action.LineShare.name")) {
    private val applicationSettings = service<ApplicationSettings>()
    private val settings = project.service<ProjectSettings>()
    private val runtime = project.service<LineShareRuntime>()
    private lateinit var editor: EditorEx
    private lateinit var document: Document
    private lateinit var removeButton: Cell<javax.swing.JButton>
    private lateinit var tryButton: Cell<javax.swing.JButton>
    private var tryText: MutableMap<String, Any> = mutableMapOf()
    private lateinit var updateButton: Cell<javax.swing.JButton>
    private lateinit var output: Cell<JBTextArea>
    private lateinit var rangeMarker: RangeMarker
    override fun createPanel(): DialogPanel {
        // https://plugins.jetbrains.com/docs/intellij/kotlin-ui-dsl-version-2.html#panelindent

        val editorFactory = EditorFactory.getInstance()
        document = editorFactory.createDocument("")
        editor = editorFactory.createEditor(document, project) as EditorEx
        runtime.rule?.let {
            refreshEditor(it)
        }

        val editorSettings: EditorSettings = editor.settings

        // 设置 Editor 大小
        editor.component.preferredSize = Dimension(600, 250)

        // 关闭虚拟空间
        editorSettings.isVirtualSpace = false

        // 关闭标记位置（断点位置）
        editorSettings.isLineMarkerAreaShown = false

        // 关闭缩减指南
        editorSettings.isIndentGuidesShown = false

        // 显示行号
        editorSettings.isLineNumbersShown = true

        // 支持代码折叠
        editorSettings.isFoldingOutlineShown = true

        // 附加行，附加列（提高视野）
        editorSettings.additionalColumnsCount = 3
        editorSettings.additionalLinesCount = 3

        // 不显示换行符号
        editorSettings.isCaretRowShown = false

        // 设置 Kotlin 语法高亮
        val fileType: FileType = FileTypeManager.getInstance().getFileTypeByExtension("kts")
        editor.settings.isHighlightSelectionOccurrences = true
        val scheme = EditorColorsManager.getInstance().globalScheme
        editor.colorsScheme = scheme
        val highlighter: EditorHighlighter =
            EditorHighlighterFactory.getInstance().createEditorHighlighter(project, fileType)
        editor.highlighter = highlighter

        return panel {
            group(message("settings.project.label")) {
                row {
                    label(message("settings.project.label.remote"))
                    textField().text(settings.remote)
                }

                row {
                    label(message("settings.project.label.matchRule"))
                    val cb = comboBox(
                        CollectionComboBoxModel(applicationSettings.getAllRule()),
                        object : SimpleListCellRenderer<Rule>() {
                            override fun customize(
                                p0: JList<out Rule>,
                                rule: Rule?,
                                p2: Int,
                                p3: Boolean,
                                p4: Boolean
                            ) {
                                text = rule?.name ?: ""
                                icon = rule?.icon
                            }
                        }).bindItem({
                        runtime.rule
                    }, {
                    })
                        .comment(message("settings.project.ruleList.comment"))
                        .component
                    cb.addItemListener {
                        if (it.stateChange == ItemEvent.SELECTED) {
                            val selectedRule = it.itemSelectable.selectedObjects.first() as Rule
                            refreshEditor(selectedRule)
                            //确定选择的规则是否原型
                            if (selectedRule is CustomRule) {
                                //确定是否是修改过的原型
                                updateButton.component.isEnabled = false
                                if (selectedRule.id < rules.size) {
                                    removeButton.component.text = "reset"
                                } else {
                                    removeButton.component.text = "remove"
                                }
                                removeButton.component.isVisible = true
                            } else {
                                removeButton.component.isEnabled = false
                                removeButton.component.isVisible = false
                            }
                        }
                    }
                    button(
                        "add"
                    ) {
                        val ruleName = JOptionPane.showInputDialog(getFrame(), "输入规则名")
                        // 处理用户输入
                        if (ruleName != null && ruleName.isNotEmpty()) {
                            WriteCommandAction.runWriteCommandAction(project) {
                                applicationSettings.customRules.add(CustomRule(ruleName))
                            }
                        }
                    }
                    tryButton = button(
                        "try"
                    ) {
                        innerEval {
                            try {
                                it.eval(document.getText(TextRange(0, rangeMarker.textRange.startOffset)))
                                val ruleName = it.eval("ruleName") as String
                                val ruleOriginMatch = (it.eval("ruleOriginMatch") as Regex)
                                tryText["name"] = ruleName
                                tryText["match"] = ruleOriginMatch
                                tryText["code"] = document.getText(rangeMarker.textRange)
                                val res: String = it.eval(tryText["code"] as String) as String
                                output.component.text = """
                                        ruleName=${ruleName}
                                        ruleOriginMatch=${ruleOriginMatch.toPattern()}
                                        output=${res}
                                    """.trimIndent()
                                updateButton.component.isEnabled = true
                                res
                            } catch (exception: Exception) {
                                output.component.text = """
                                        ${exception.printToString()}
                                    """.trimIndent()
                                return@innerEval ""
                            }
                        }
                    }
                    updateButton = button(
                        "update"
                    ) {
                        tryButton.component.isEnabled = false
                        val customRule = CustomRule(tryText["name"] as String)
                        customRule.originMatch = tryText["match"] as Regex
                        customRule.template = tryText["code"] as String
                        applicationSettings.customRules.add(customRule)
                    }
                    updateButton.component.isEnabled = false
                    removeButton = button(
                        "remove/reset",
                        actionListener = {
                            getFrame()?.let {
                                val state = (cb.selectedItem as KProperty0<*>).get() as Int
                            }
                        }
                    )
                }

            }
            panel {
                row {
                    scrollCell(editor.component)
                }
                row {
                    output = textArea().apply {
                        columns(50)
                        rows(3)
                    }
                }
            }

            row {
                browserLink(message("settings.report-bug.title"), LineShareBundle.ISSUE_URL)
            }
        }
    }

    private fun refreshEditor(selectedRule: Rule) {
        WriteCommandAction.runWriteCommandAction(project) {
            val ruleName = selectedRule.name
            val ruleIcon = (selectedRule.icon as? CachedImageIcon)?.originalPath ?: ""
            val originMatch = selectedRule.originMatch.pattern.replace("\\", "\\\\")
            val codeTemplate = arrayOf(
                "// *************变量脚本提示*************\n${preScript(runtime.property)}\n// *************规则详情*************\nvar ruleName=\"",
                ruleName.ifEmpty { "blank" },
                "\"\nvar ruleIcon=\"",
                ruleIcon.ifEmpty { "blank" },
                "\"\nvar ruleOriginMatch=\"",
                originMatch.ifEmpty { "blank" },
                "\".toRegex()\n// *************规则正文*************\n",
                selectedRule.template,
            )
            document.setText(
                codeTemplate.joinToString("")
            )
            var start = 0
            codeTemplate.forEachIndexed { index, value ->
                if (!arrayOf(1, 3, 5, 7).contains(index)) {
                    lock(start, start + value.length)
                }
                if (index == 7) {
                    // template
                    rangeMarker = document.createRangeMarker(start, start + value.length)
                }
                start += value.length
            }
        }
    }

    private fun lock(start: Int, end: Int) {
        var block = document.createGuardedBlock(start, end)
        block.isGreedyToLeft = true
        block.isGreedyToRight = true
        // 添加高亮显示（可选）
        highlightLockedArea(start, end)
    }

    private fun highlightLockedArea(startOffset: Int, endOffset: Int) {
        val markupModel: MarkupModel = editor.markupModel
        val attributes = TextAttributes()
        attributes.backgroundColor = JBColor.LIGHT_GRAY
        attributes.effectColor = JBColor.GRAY
        attributes.effectType = EffectType.BOXED
        markupModel.addRangeHighlighter(
            startOffset,
            endOffset,
            1,
            attributes,
            HighlighterTargetArea.EXACT_RANGE
        )
    }

    private fun getFrame(): IdeFrameImpl? {
        return WindowManagerEx.getInstanceEx().getFrame(project)
    }
}